/**
 * User控制器模块
 * 
 * 说明：
 * 中间件处理路由请求：
 * 1.req.params --> 路由参数   /:id ->req.params.id
 * 2.req.query --> url查询串   ?k1=v1&k2=v2 -> req.query.k1, req.query.k2
 * 3.req.body --> 数据对象 {k1:v1 k2:v2}  -> req.body.k1, req.body.k2
 * 
 * 中间件进行异步封装 (async/await), 不会直接执行，需要进行函数立即执行的方式。
 */

const express = require("express");

const util = require("../common/util");
/**
 * @typedef {UserDB}
 */
const UserDB = require("../model/db/user");

const config = require("../common/config");

/**
 * 获取用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function find(req, res) {
    let db = UserDB.getInstance(); // 使用新创建的 MySQLUserDB 类
    let result = await db.find(req.params.id); // 使用 MySQLUserDB 类中的 find 方法
    //await db.close():
    result.fullAvatar = config.serverUrl + "/" + result.avatar;
    result.roleName = (()=>{
        if(result.role === 1){
            return "超级管理员组";
        }else if(result.role === 2){
            return "普通用户组";
        }else if(result.role === 3){
            return "普通管理员组";
        }
    })
    util.logFormat(`获取【${req.params.id}】用户信息%O`, result);
    res.json(util.FormatJSONData(200, `获取用户信息【${req.params.id}】成功`,
        result));
}

/**
 * 通过指定电话号码获取用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function findByPhone(req, res) {
    let db = UserDB.getInstance(); // 使用新创建的 MySQLUserDB 类
    let result = await db.findByPhone(req.params.id); // 使用 MySQLUserDB 类中的 find 方法
    //await db.close():
    util.logFormat(`获取【${req.params.id}】用户信息%O`, result);
    res.json(util.FormatJSONData(200, `获取用户信息【${req.params.id}】成功`,result));
}

/**
 * 获取用户列表信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function findAll(req, res) {
    //1.处理输入的数据
    //FIXME：输入数据的正确性校验，一致性校验，完整性校验
    let limit = req.query.limit ? req.query.limit : -1;
    let offset = req.query.offset ? req.query.offset : -1;
    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.findAll(limit, offset);

    //3.处理输出数据
    //await db.close():
    util.logFormat(`获取【limit=${limit}&offset=${offset}】用户信息%O`, result);
    res.json(util.FormatJSONData(200, `获取用户信息列表【${req.params.id}】成功`,
        result));
}


/**
 * 新增用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function add(req, res) {
    let user = {
        username: req.body.username,
        password: util.md5pwd(req.body.password),
        nickname: req.body.nickname,
        truename: req.body.truename,
        avatar: req.body.avatar,
        role: req.body.role,
        lastLoginime: new Date(), // 使用当前时间对象代替 0
        lastLoginIp: "never login",
        loginCount: 0, // 添加 login_count 字段
        email: req.body.email, // 添加 email 字段
        phoneNumber: req.body.phoneNumber, // 添加 phone_number 字段
        createdIp: util.getReqRemoteIP(req)
    };

    // 2. 访问数据
    let db = UserDB.getInstance(); // 使用新创建的 MySQLUserDB 类
    let result = await db.add(user); // 使用 MySQLUserDB 类中的 add 方法

    util.log(`新增用户信息:lastID${result}`);
    res.json(util.FormatJSONData(201, `新增用户信息`, { lastID: result }));
}
/**
 * 修改用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function update(req, res) {
    //FIXME:req.body的数据安全性校验（需要做）
    let user = {
        id: req.params.id,
        username: req.body.username,
        password: util.md5pwd(req.body.password),
        nickname: req.body.nickname,
        truename: req.body.truename,
        avatar: req.body.avatar,
        role: req.body.role,
        email: req.body.email,
        phoneNumber: req.body.phoneNumber,
        isVerified: req.body.isVerified,
        accountStatus: req.body.accountStatus,
    };

    //2.访问数据
    let db = UserDB.getInstance();
    //FIXME:插入数据前，考虑校验是否已存在ISBN
    let result = await db.update(user);

    //3.处理输出数据
    //await db.close():
    util.log(`更新用户信息:changes->${result}`);
    res.json(util.FormatJSONData(200, `更新用户信息`, { changes: result }));
}


/**
 * 删除用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function remove(req, res) {
    //FIXME:数据合法性校验
    let userId = req.params.id;
    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.remove(userId);

    //3.处理输出数据
    //await db.close():
    util.log(`删除用户信息:changes->${result}`);
    res.json(util.FormatJSONData(204, `删除用户信息`, { changes: result }));
}


/**
 * 获取用户总数
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function getCount(req, res) {
    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.getCount();

    //3.处理输出数据
    //await db.close():
    util.log(`获取用户总数:${result}`);
    res.json(util.FormatJSONData(200, `获取用户总数`, result));
}

/**
 * 按关键字搜索用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function search(req, res) {
    //1.处理输入的数据
    //FIXME：输入数据的正确性校验，一致性校验，完整性校验
    let q = req.query.q;
    let limit = req.query.limit ? req.query.limit : -1;
    let offset = req.query.offset ? req.query.offset : -1;
    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.search(q, limit, offset);

    //3.处理输出数据
    //await db.close():
    util.logFormat(`获取关键字为【${q}】【limit=${limit}&offset=${offset}】用户信息%O`, result);
    res.json(util.FormatJSONData(200, `获取指定关键字的用户信息列表`, result));
}

/**
 * 注册用户信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function register(req, res) {
    let user = {
        username: req.body.username,
        password: util.md5pwd(req.body.password),
        truename: req.body.truename,
        role: 2,
        phoneNumber: req.body.phoneNumber,
        isVerified: false,
        lastLoginIp: "never login",
        createdTime: new Date(),
        createdIp: util.getReqRemoteIP(req),
        updatedTime: new Date(),
        accountStatus: "active"
    };

    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.register(user);

    //3.处理输出数据
    //await db.close():
    util.log(`注册用户信息:lastID${result}`);
    res.json(util.FormatJSONData(201, `注册用户`, { lastID: result }));
}




/**
 * 用户登录
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function login(req, res) {
    let phoneNumber = req.body.phoneNumber;
    let password = util.md5pwd(req.body.password);

    let msg = `用户【${phoneNumber}】登录失败，请检查用户名和密码`;
    let data = { loginStatus: "failed" };
    //2.访问数据
    let db = UserDB.getInstance();
    let result = await db.login(phoneNumber, password);
    if (result) {
        msg = `用户【${phoneNumber}】登录成功`;
        data = {
            loginStatus: "success",
            userId: result.id,
            username: result.username,
            nickname: result.nickname,
            truename: result.truename,
            role: result.role,
        };
        let lastLogin = {
            time: Date.now(),
            ip: util.getReqRemoteIP(req),
        };
        await db.touch(phoneNumber, lastLogin);
        //使用session保存登录状态
        req.session.isLogin = true;
        req.session.user = result;
    }
    //3.处理输出数据
    //await db.close():
    util.log(`用户【${phoneNumber}】登录，用户信息%O`, result);
    res.json(util.FormatJSONData(200, msg, data));
}


/**
 * 用户退出
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function logout(req, res) {
    if (req.session.user) {
        let username = req.session.user.username;
        req.session.destroy((err) => util.log(err));

        util.log(`用户【${username}】退出，用户session值【${req.session}】`);

        res.json(util.FormatJSONData(200, `用户【${username}】退出系统`,
            { logoutStatus: "success" }));
    } else {
        res.json(util.FormatJSONData(200, `非正确访问路径`));
    }
}

/**
 * 修改个人信息
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function changeInfo(req, res) {
    //FIXME:req.body的数据安全性校验（需要做）
    let info = {
        nickname: req.body.nickname,
        truename: req.body.truename,
        avatar: req.body.avatar,
    };

    let id = req.session.user.id;
    //2.访问数据
    let db = UserDB.getInstance();
    //FIXME:插入数据前，考虑校验是否已存在
    let result = await db.changeInfo(id, info);

    //3.处理输出数据
    //await db.close():
    util.log(`修改个人信息:changes->${result} -->${req.session.user.id}`);
    res.json(util.FormatJSONData(200, `修改个人信息成功`, { changes: result }));
}

/**
 * 修改个人密码
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function changePassword(req, res) {
    //FIXME:req.body的数据安全性校验（需要做）
    let password = util.md5pwd(req.body.password);

    let id = req.session.user.id;
    //2.访问数据
    let db = UserDB.getInstance();
    //FIXME:插入数据前，考虑校验是否已存在ISBN
    let result = await db.changePassword(id, password);

    //3.处理输出数据
    //await db.close():
    util.log(`修改个人密码:changes->${result}`);
    res.json(util.FormatJSONData(200, `修改个人密码成功`, { changes: result }));
}

/**
 * 重置个人密码
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应 
 */
async function resetPassword(req, res) {
    //FIXME:req.body的数据安全性校验（需要做）
    let password = util.md5pwd("111111");

    let id = req.params.id;
    //2.访问数据
    let db = UserDB.getInstance();
    //FIXME:插入数据前，考虑校验是否已存在ISBN
    let result = await db.changePassword(id, password);

    //3.处理输出数据
    //await db.close():
    util.log(`重置个人密码:changes->${result}`);
    res.json(util.FormatJSONData(200, `重置个人密码成功`, { changes: result }));
}
module.exports = {
    find,
    findByPhone,
    findAll,
    add,
    update,
    remove,
    getCount,
    register,
    login,
    logout,
    search,
    changeInfo,
    changePassword,
    resetPassword,
}